#define _CRT_SECURE_NO_WARNINGS 1
#include "string.h"

namespace HQ
{
	const size_t string::npos = -1;
	//string::string()
	//{
	//	// _str = nullptr // err, 因为c_str返回的字符串不正常
	//	_str = new char[1]{'\0'}; 
	//	_size = 0;
	//	_capacity = 0;
	//}

	string::iterator string::begin()
	{
		return _str;
	} 

	string::iterator string::end()
	{
		return _str + _size;
	}

	string::const_iterator string::begin() const
	{
		return _str;
	}

	string::const_iterator string::end() const
	{
		return _str + _size;
	}

	string::string(const char* str)
		:_size(strlen(str)) // 不算\0
	{
		// 三个strlen效率低，用_size来初始化
		_str = new char[_size + 1];
		_capacity = _size; // 不算\0

		strcpy(_str, str);
	}

	string::string(const string& str)
		:_str(new char[str._capacity + 1])
		,_size(str._size)
		,_capacity(str._capacity)
	{
		strcpy(_str, str._str);
	}

	string& string::operator=(const string& str)
	{
		// 考虑到两个字符串的长度可能不太一样
		// 干脆直接销毁旧的，新开一个拷贝过去
		if (this != &str) {
			char* tmp = new char[str._capacity + 1];
			strcpy(tmp, str._str);

			delete[] _str;
			_str = tmp;
			_size = str._size;
			_capacity = str._capacity;
		}

		return *this;
	}

	string::~string()
	{
		delete[] _str; // 不会产生矛盾
		_str = nullptr;
		_size = _capacity = 0;
	}

	const char* string::c_str() const
	{
		return _str;
	}

	size_t string::size() const
	{
		return _size;
	}

	char& string::operator[](size_t pos) 
	{
		assert(pos < _size);
		return _str[pos];
	}

	const char& string::operator[](size_t pos) const
	{
		assert(pos < _size);
		return _str[pos];
	}

	void string::reserve(size_t n)
	{
		if (n > _capacity) {
			// 脑子里有个流程图即可
			// 开辟新空间->拷贝->释放就空间->更新
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);

			delete[] _str;
			_str = tmp;	
			_capacity = n;
		}
	}

	void string::push_back(char ch)
	{
		if (_size == _capacity) {
			size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newCapacity);
		}

		_str[_size++] = ch;
		_str[_size] = '\0';

		// insert(_size, ch);
	}

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		reserve(_size + len);

		strcpy(_str + _size, str); // 能覆盖'\0'并且带了'\0'
		_size += len;

		// insert(_size, str);
	}

	string& string::operator+=(char ch)
	{
		push_back(ch);
		return *this;
	}

	string& string::operator+=(const char* str)
	{
		append(str);
		return *this;
	}

	void string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);
		// 谨慎使用
		if (_size == _capacity) {
			size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newCapacity);
		}

		size_t end = _size;
		while (end >= pos) {
			_str[end + 1] = _str[end];
			if (end == 0) break; // end == -1 -> err
			--end;
		}
		_str[pos] = ch;
		++_size;
	}

	void string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);
		size_t len = strlen(str);
		reserve(_size + len);

		size_t end = _size;
		while (end >= pos) {
			_str[end + len] = _str[end];
			if (end == 0) break; // end == -1 -> err
			--end;
		}

		memcpy(_str + pos, str, len);
		_size += len;
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		// 当len == npos时候，条件判断一定成立
		if (len >= _size - pos) {
			// pos后(含)全删完
			_str[pos] = '\0';
			_size = pos;
		}
		else {
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		for (size_t i = pos; i < _size; i++) {
			if (_str[i] == ch) {
				return i;
			}
		}

		return npos;
	}

	size_t string::find(const char* sub, size_t pos)
	{
		char* p = strstr(_str + pos, sub);

		return p == NULL ? npos : p - _str;
	}

	void string::swap(string& str)
	{
		std::swap(_str, str._str);
		std::swap(_size, str._size);
		std::swap(_capacity, str._capacity);
	}

	string string::substr(size_t pos, size_t len)
	{
		if (len > _size - pos) {

			string sub(_str + pos);
			return sub;
		}
		else {
			string sub;
			sub.reserve(len);
			for (size_t i = pos; i < pos + len ; i++) {
				sub += _str[i];
			}
			sub._size = len;
			return sub;
		}
	}

	bool string::operator<(const string& s) const
	{
		return strcmp(_str, s._str) < 0;
	}

	bool string::operator>(const string& s) const
	{
		return !(*this <= s);
	}

	bool string::operator<=(const string& s) const
	{
		return (*this == s || *this < s);
	}

	bool string::operator>=(const string& s) const
	{
		return !(*this < s);
	}

	bool string::operator==(const string& s) const
	{
		return strcmp(_str, s._str) == 0;
	}

	bool string::operator!=(const string& s) const
	{
		return !(*this == s);
	}

	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}

	istream& operator>> (istream& is, string& str)
	{
		str.clear(); // 要覆盖先前的内容，先清除一下
		char ch = is.get();
		//is >> ch; // 拿不到空格和换行


		while (ch != ' ' && ch != '\n') {
			str += ch;
			ch = is.get();
		}

		return is;
	}

	ostream& operator<< (ostream& os, const string& str)
	{
		for (size_t i = 0; i < str.size(); i++) {
			os << str[i];
		}

		return os;
	}
}